home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / sdk / vfw11.win / vfwdk / aainit.c_ / aainit.bin
Encoding:
Text File  |  1993-11-19  |  52.5 KB  |  1,804 lines

  1. //==========================================================================;
  2. //
  3. //  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. //  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. //  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. //  PURPOSE.
  7. //
  8. //  Copyright (c) 1992, 1993  Microsoft Corporation.  All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. //  aainit.c
  13. //
  14. //  Description:
  15. //      This file contains initialization and termination code for the
  16. //      application (as well as some rarely used stuff).
  17. //
  18. //
  19. //==========================================================================;
  20.  
  21. #include <windows.h>
  22. #include <windowsx.h>
  23. #include <mmsystem.h>
  24. #include <commdlg.h>
  25. #ifndef WIN32
  26. #include <shellapi.h>
  27. #endif 
  28. #include <mmreg.h>
  29. #include <msacm.h>
  30. #include <stdarg.h>
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <memory.h>
  35.  
  36. #include "acmthunk.h"
  37. #include "appport.h"
  38. #include "acmapp.h"
  39.  
  40. #include "debug.h"
  41.  
  42.  
  43. //
  44. //
  45. //
  46. TCHAR   gszSecConfig[]          = TEXT("Configuration");
  47.  
  48. TCHAR   gszKeyOptions[]         = TEXT("Options");
  49. TCHAR   gszFormatOptions[]      = TEXT("%u");
  50.  
  51. TCHAR   gszKeyWindow[]          = TEXT("Window");
  52. TCHAR   gszKeyFont[]            = TEXT("Font");
  53. TCHAR   gszKeyInitialDirOpen[]  = TEXT("InitialDirOpen");
  54. TCHAR   gszKeyInitialDirSave[]  = TEXT("InitialDirSave");
  55. TCHAR   gszKeyLastSaveFile[]    = TEXT("LastSaveFile");
  56.  
  57.  
  58. //==========================================================================;
  59. //
  60. //  Application helper functions and rarely called stuff...
  61. //
  62. //
  63. //==========================================================================;
  64.  
  65. //--------------------------------------------------------------------------;
  66. //
  67. //  DWORD AppGetWindowsVersion
  68. //
  69. //  Description:
  70. //      This function returns the version of Windows that the application
  71. //      is running on plus some platform information.
  72. //
  73. //  Arguments:
  74. //      PTSTR pach: Options pointer to buffer to receive text string of
  75. //      the Windows version and platform.
  76. //
  77. //  Return (LRESULT):
  78. //      The return value will be the version and platform information of
  79. //      the current operating system in the following format:
  80. //
  81. //      0xPPPPMMRR where:
  82. //
  83. //      MM      :   major version of Windows
  84. //      RR      :   minor version (revision) of Windows
  85. //      PPPP    :   the platform the application is running on which
  86. //                  will be one of the following:
  87. //
  88. //                  #ifdef WIN32
  89. //                      the HIWORD() is RESERVED except for the high bit:
  90. //                          high bit is 0 = Windows NT
  91. //                          high bit is 1 = Win32s/Windows 3.1
  92. //                  #else
  93. //                      0xMMRR = Major and Minor version of [MS-]DOS
  94. //                      GetWinFlags() & 0x8000 = Windows on OS/2 (WLO)
  95. //                      GetWinFlags() & 0x4000 = Windows on Windows NT (WOW)
  96. //                  #endif
  97. //
  98. //
  99. //--------------------------------------------------------------------------;
  100.  
  101. LRESULT FNGLOBAL AppGetWindowsVersion
  102. (
  103.     PTSTR                   pszEnvironment,
  104.     PTSTR                   pszPlatform
  105. )
  106. {
  107.  
  108.     BYTE    bVerWinMajor;
  109.     BYTE    bVerWinMinor;
  110.     UINT    uVerEnv;
  111.     DWORD   dw;
  112.     LRESULT lr;
  113.  
  114.     dw = GetVersion();
  115.  
  116.     //
  117.     //  massage the version information into something intelligent
  118.     //
  119.     //
  120.     bVerWinMajor = LOBYTE(LOWORD(dw));
  121.     bVerWinMinor = HIBYTE(LOWORD(dw));
  122.     uVerEnv      = HIWORD(dw);
  123.     lr = MAKELPARAM(((UINT)bVerWinMajor << 8) | bVerWinMinor, uVerEnv);
  124.  
  125.     //
  126.     //  if caller wants the environment string version...
  127.     //
  128.     if (NULL != pszEnvironment)
  129.     {
  130.     //
  131.     //
  132.     //
  133. #ifdef WIN32
  134. {
  135.     static TCHAR    szFormatVersion[]   = TEXT("%s Version %u.%.2u");
  136.     static TCHAR    szEnvWinNT[]        = TEXT("Windows NT");
  137.     static TCHAR    szEnvWin32s[]       = TEXT("Win32s");
  138.  
  139.     wsprintf(pszEnvironment, szFormatVersion,
  140.              (LPSTR)((0x8000 & uVerEnv) ? szEnvWin32s : szEnvWinNT),
  141.              bVerWinMajor, bVerWinMinor);
  142. }
  143. #else
  144. {
  145. #ifndef WF_WINNT
  146.     #define WF_WINNT        0x4000
  147.     #define WF_WLO          0x8000
  148. #endif
  149. #ifndef WF_CPUMASK
  150.     #define WF_CPUMASK      0xFC000000
  151.     #define WF_CPU_X86      0
  152.     #define WF_CPU_R4000    1
  153.     #define WF_CPU_ALPHA    2
  154.     #define WF_CPU_CLIPPER  3
  155. #endif
  156.  
  157.     static TCHAR    szFormatSubSys[]= TEXT("Windows Version %u.%.2u (%s%s)\n%s Subsystem, DOS Version %u.%.2u");
  158.     static TCHAR    szFormatDOS[]   = TEXT("Windows Version %u.%.2u (%s%s)\nDOS Version %u.%.2u");
  159.     static TCHAR    szSubSysWLO[]   = TEXT("WLO");
  160.     static TCHAR    szSubSysWOW[]   = TEXT("WOW");
  161.     static TCHAR    szModeEnhanced[]= TEXT("Enhanced");
  162.     static TCHAR    szModeStandard[]= TEXT("Standard");
  163.     static TCHAR    szEnvPaging[]   = TEXT(", Paging");
  164.  
  165.     DWORD   dwWinFlags;
  166.     PTSTR   pszMode;
  167.  
  168.     BYTE    bVerEnvMajor    = HIBYTE(LOWORD(uVerEnv));
  169.     BYTE    bVerEnvMinor    = LOBYTE(LOWORD(uVerEnv));
  170.  
  171.     dwWinFlags = GetWinFlags();
  172.  
  173.     pszMode = (dwWinFlags & WF_ENHANCED) ? szModeEnhanced : szModeStandard;
  174.     if (dwWinFlags & (WF_WLO | WF_WINNT))
  175.     {
  176.         wsprintf(pszEnvironment, szFormatSubSys, bVerWinMajor, bVerWinMinor,
  177.                  (LPSTR)pszMode,
  178.                  (LPSTR)((dwWinFlags & WF_PAGING) ? szEnvPaging : gszNull),
  179.                  (LPSTR)((dwWinFlags & WF_WINNT) ? szSubSysWOW : szSubSysWLO),
  180.                  bVerEnvMajor, bVerEnvMinor);
  181.     }
  182.     else
  183.     {
  184.         wsprintf(pszEnvironment, szFormatDOS, bVerWinMajor, bVerWinMinor,
  185.                  (LPSTR)pszMode,
  186.                  (LPSTR)((dwWinFlags & WF_PAGING) ? szEnvPaging : gszNull),
  187.                  bVerEnvMajor, bVerEnvMinor);
  188.     }
  189. }
  190. #endif
  191.     }
  192.  
  193.     //
  194.     //  if caller wants the platform string version...
  195.     //
  196.     if (NULL != pszPlatform)
  197.     {
  198. #ifdef WIN32
  199. {
  200.     static TCHAR    szFormatPlatform[]  = TEXT("%s%u, %u Processor(s)");
  201.     static TCHAR    szProcessorIntel[]  = TEXT("Intel ");
  202.     static TCHAR    szProcessorMIPS[]   = TEXT("MIPS R");
  203.     static TCHAR    szProcessorAlpha[]  = TEXT("DEC Alpha ");
  204.     static TCHAR    szProcessorDunno[]  = TEXT("Dunno zYz");
  205.  
  206.     SYSTEM_INFO sysinfo;
  207.     PTSTR       pszProcessor;
  208.  
  209.     //
  210.     //  this is absolutely silly. one would think that the dwOemId member
  211.     //  would provide something useful like the processor class... but
  212.     //  no, it doesn't--it is always 0.
  213.     //
  214.     GetSystemInfo(&sysinfo);
  215.     switch (sysinfo.dwProcessorType)
  216.     {
  217.         case PROCESSOR_INTEL_386:
  218.         case PROCESSOR_INTEL_486:
  219.         case PROCESSOR_INTEL_860:
  220.             pszProcessor = szProcessorIntel;
  221.             break;
  222.  
  223.         case PROCESSOR_MIPS_R2000:
  224.         case PROCESSOR_MIPS_R3000:
  225.         case PROCESSOR_MIPS_R4000:
  226.             pszProcessor = szProcessorMIPS;
  227.             break;
  228.  
  229.         case PROCESSOR_ALPHA_21064:
  230.             pszProcessor = szProcessorAlpha;
  231.             break;
  232.  
  233.         default:
  234.             pszProcessor = szProcessorDunno;
  235.             break;
  236.     }
  237.  
  238.     //
  239.     //
  240.     //
  241.     wsprintf(pszPlatform, szFormatPlatform, (LPSTR)pszProcessor,
  242.              sysinfo.dwProcessorType, sysinfo.dwNumberOfProcessors);
  243. }
  244. #else
  245. {
  246.     static TCHAR    szPlat286[]         = TEXT("80286");
  247.     static TCHAR    szPlat386[]         = TEXT("80386");
  248.     static TCHAR    szPlat486[]         = TEXT("i486");
  249.     static TCHAR    szPlatR4000[]       = TEXT("MIPS R4000, Emulation: ");
  250.     static TCHAR    szPlatAlpha21064[]  = TEXT("Alpha 21064, Emulation: ");
  251.     static TCHAR    szPlatClipper[]     = TEXT("Clipper, Emulation: ");
  252.     static TCHAR    szPlat80x87[]       = TEXT(", 80x87");
  253.  
  254.     DWORD   dwWinFlags;
  255.  
  256.     dwWinFlags = GetWinFlags();
  257.     pszPlatform[0] = '\0';
  258.  
  259.     if (dwWinFlags & (WF_WLO | WF_WINNT))
  260.     {
  261.         switch ((dwWinFlags & WF_CPUMASK) >> 26)
  262.         {
  263.             case WF_CPU_X86:
  264.                 break;
  265.  
  266.             case WF_CPU_R4000:
  267.                 lstrcpy(pszPlatform, szPlatR4000);
  268.                 break;
  269.  
  270.             case WF_CPU_ALPHA:
  271.                 lstrcpy(pszPlatform, szPlatAlpha21064);
  272.                 break;
  273.  
  274.             case WF_CPU_CLIPPER:
  275.                 lstrcpy(pszPlatform, szPlatClipper);
  276.                 break;
  277.         }
  278.     }
  279.  
  280.     if (dwWinFlags & WF_CPU286)
  281.         lstrcat(pszPlatform, szPlat286);
  282.     else if (dwWinFlags & WF_CPU386)
  283.         lstrcat(pszPlatform, szPlat386);
  284.     else if (dwWinFlags & WF_CPU486)
  285.         lstrcat(pszPlatform, szPlat486);
  286.  
  287.     if (dwWinFlags & WF_80x87)
  288.         lstrcat(pszPlatform, szPlat80x87);
  289. }
  290. #endif
  291.     }
  292.  
  293.     //
  294.     //  return the result
  295.     //
  296.     return (lr);
  297. } // AppGetWindowsVersion()
  298.  
  299.  
  300. //--------------------------------------------------------------------------;
  301. //
  302. //  LRESULT AppWinIniChange
  303. //
  304. //  Description:
  305. //      This function is responsible for handling the WM_WININICHANGE
  306. //      message. This message is sent when modifications have been made
  307. //      to WIN.INI (from SystemParametersInfo() or other sources).
  308. //
  309. //      An application should re-enumerate system metrics (GetSystemMetrics)
  310. //      and system color (GetSystemColors) information that it has cached.
  311. //      Note that checking the section that was modified should be done if
  312. //      some enumerations are time consuming.
  313. //
  314. //  Arguments:
  315. //      HWND hwnd: Handle to window that generated the WM_INITMENUPOPUP
  316. //      message.
  317. //
  318. //      LPCTSTR pszSection: Pointer to section name that has been modified
  319. //      in WIN.INI. Note that this argument might be NULL (sent by apps
  320. //      that were written incorrectly!). If it is NULL, then this application
  321. //      should re-enumerate ALL metrics, colors, etc.
  322. //
  323. //  Return (LRESULT):
  324. //      The return value is zero if the message is processed.
  325. //
  326. //
  327. //--------------------------------------------------------------------------;
  328.  
  329. LRESULT FNGLOBAL AppWinIniChange
  330. (
  331.     HWND                    hwnd,
  332.     LPCTSTR                 pszSection
  333. )
  334. {
  335.     DPF(1, "AppWinIniChanged(hwnd=%Xh, pszSection='%s')",
  336.             hwnd, (NULL == pszSection) ? TEXT("(null)") : pszSection);
  337.  
  338.     //
  339.     //  we processed the message...
  340.     //
  341.     return (0L);
  342. } // AppWinIniChange()
  343.  
  344.  
  345. //--------------------------------------------------------------------------;
  346. //
  347. //  HFONT AppChooseFont
  348. //
  349. //  Description:
  350. //      This function is a wrapper for the ChooseFont() common dialog.
  351. //      The purpose of this function is to let the user choose a font that
  352. //      looks good to them--regardless of how stupid it really looks.
  353. //
  354. //  Arguments:
  355. //      HWND hwnd: Handle to parent window for chooser dialog.
  356. //
  357. //      HFONT hfont: Handle to current font (default for chooser dialog).
  358. //
  359. //      PLOGFONT plf: Pointer to optional LOGFONT structure to receive a
  360. //      copy of the LOGFONT information for the newly chosen font.
  361. //
  362. //  Return (HFONT):
  363. //      The return value is the newly chosen font. If no new font was chosen
  364. //      then the return value is NULL.
  365. //
  366. //
  367. //--------------------------------------------------------------------------;
  368.  
  369. HFONT FNGLOBAL AppChooseFont
  370. (
  371.     HWND                    hwnd,
  372.     HFONT                   hfont,
  373.     PLOGFONT                plf
  374. )
  375. {
  376.     LOGFONT             lf;
  377.     CHOOSEFONT          cf;
  378.     BOOL                f;
  379.     HFONT               hfontNew;
  380.  
  381.     //
  382.     //  get the font info for the current font...
  383.     //
  384.     GetObject(hfont, sizeof(LOGFONT), (LPVOID)&lf);
  385.  
  386.     //
  387.     //  fill in the choosefont structure
  388.     //
  389.     cf.lStructSize  = sizeof(CHOOSEFONT);
  390.     cf.hwndOwner    = hwnd;
  391.     cf.hDC          = NULL;
  392.     cf.Flags        = CF_SCREENFONTS |
  393.                       CF_INITTOLOGFONTSTRUCT |
  394.                       CF_FIXEDPITCHONLY |
  395.                       CF_FORCEFONTEXIST;
  396.     cf.lCustData    = 0;
  397.     cf.lpfnHook     = NULL;
  398.     cf.hInstance    = NULL;
  399.     cf.nFontType    = SCREEN_FONTTYPE;
  400.     cf.lpLogFont    = (LPLOGFONT)&lf;
  401.  
  402.     //
  403.     //  splash a dialog into the user's face..
  404.     //
  405.     hfontNew = NULL;
  406.     f = ChooseFont(&cf);
  407.     if (f)
  408.     {
  409.         //
  410.         //  create the new font..
  411.         //
  412.         hfontNew = CreateFontIndirect(&lf);
  413.         if (NULL == hfontNew)
  414.             return (NULL);
  415.  
  416.         //
  417.         //  copy the logfont structure if caller wants it
  418.         //
  419.         if (NULL != plf)
  420.             *plf = lf;
  421.     }
  422.  
  423.     //
  424.     //  return the new font (if one was chosen)
  425.     //
  426.     return (hfontNew);
  427. } // AppChooseFont()
  428.  
  429.  
  430.  
  431. //--------------------------------------------------------------------------;
  432. //  
  433. //  BOOL AppProfileWriteBytes
  434. //  
  435. //  Description:
  436. //      This function writes a raw structure of bytes to the application's
  437. //      ini section that can later be retrieved using AppProfileReadBytes.
  438. //      This gives an application the ability to write any structure to
  439. //      the ini file and restore it later--very useful.
  440. //
  441. //      NOTE! Starting with Windows for Workgroups 3.1 there are two new
  442. //      profile functions that provide the same functionality of this
  443. //      function. Specifically, these functions are GetPrivateProfileStruct
  444. //      and WritePrivateProfileStruct. These new functions are provided
  445. //      by the Common Controls DLL. The prototypes are as follows:
  446. //
  447. //      BOOL GetPrivateProfileStruct
  448. //      (
  449. //          LPSTR       szSection,
  450. //          LPSTR       szKey,
  451. //          LPBYTE      lpStruct,
  452. //          UINT        uSizeStruct,
  453. //          LPSTR       szFile
  454. //      );
  455. //
  456. //      BOOL WritePrivateProfileStruct
  457. //      (
  458. //          LPSTR       szSection,
  459. //          LPSTR       szKey,
  460. //          LPBYTE      lpStruct,
  461. //          UINT        uSizeStruct,
  462. //          LPSTR       szFile
  463. //      );
  464. //
  465. //      If you are building an application that is for Window for Workgroups
  466. //      or newer versions of Windows, you will probably want to use the
  467. //      above functions.
  468. //
  469. //  Arguments:
  470. //      PTSTR pszSection: Pointer to section for the stored data.
  471. //
  472. //      PTSTR pszKey: Pointer to key name for the stored data.
  473. //  
  474. //      LPBYTE pbStruct: Pointer to the data to be saved.
  475. //  
  476. //      UINT cbStruct: Count in bytes of the data to store.
  477. //  
  478. //  Return (BOOL):
  479. //      The return value is TRUE if the function is successful. It is FALSE
  480. //      if it fails.
  481. //  
  482. //  
  483. //--------------------------------------------------------------------------;
  484.  
  485. BOOL FNGLOBAL AppProfileWriteBytes
  486. (
  487.     PTSTR                   pszSection,
  488.     PTSTR                   pszKey,
  489.     LPBYTE                  pbStruct,
  490.     UINT                    cbStruct
  491. )
  492. {
  493.     static TCHAR achNibbleToChar[] =
  494.     {
  495.         '0', '1', '2', '3', '4', '5', '6', '7',
  496.         '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
  497.     };
  498.     #define     NIBBLE2CHAR(x)      (achNibbleToChar[x])
  499.     
  500.     TCHAR       ach[APP_MAX_STRING_RC_CHARS];
  501.     LPTSTR      psz;
  502.     LPTSTR      pch;
  503.     UINT        cchTemp;
  504.     BOOL        fAllocated;
  505.     BOOL        fReturn;
  506.     BYTE        b;
  507.     BYTE        bChecksum;
  508.  
  509.     //
  510.     //  if pbStruct is NULL, then erase the key from the ini file, otherwise
  511.     //  format the raw bytes into a hex string and write that out...
  512.     //
  513.     fAllocated = FALSE;
  514.     psz        = NULL;
  515.     if (NULL != pbStruct)
  516.     {
  517.         //
  518.         //  check if the quick buffer can be used for formatting the output
  519.         //  text--if it cannot, then alloc space for it. note that space
  520.         //  must be available for an ending checksum byte (2 bytes for high
  521.         //  and low nibble) as well as a null terminator.
  522.         //
  523.         psz     = (LPTSTR)ach;
  524.         cchTemp = cbStruct * 2 + 3;
  525.         if (cchTemp > SIZEOF(ach))
  526.         {
  527.             psz = (LPTSTR)GlobalAllocPtr(GHND, cchTemp * sizeof(TCHAR));
  528.             if (NULL == psz)
  529.                 return (FALSE);
  530.  
  531.             fAllocated = TRUE;
  532.         }
  533.   
  534.         //
  535.         //  step through all bytes in the structure and convert it to
  536.         //  a string of hex numbers...
  537.         //
  538.         bChecksum = 0;
  539.         for (pch = psz; 0 != cbStruct; cbStruct--, pbStruct++)
  540.         {
  541.             //
  542.             //  grab the next byte and add into checksum...
  543.             //
  544.             bChecksum += (b = *pbStruct);
  545.       
  546.             *pch++ = NIBBLE2CHAR((b >> (BYTE)4) & (BYTE)0x0F);
  547.             *pch++ = NIBBLE2CHAR(b & (BYTE)0x0F);
  548.         }
  549.  
  550.         //
  551.         //  add the checksum byte to the end and null terminate the hex
  552.         //  dumped string...
  553.         //
  554.         *pch++ = NIBBLE2CHAR((bChecksum >> (BYTE)4) & (BYTE)0x0F);
  555.         *pch++ = NIBBLE2CHAR(bChecksum & (BYTE)0x0F);
  556.         *pch   = '\0';
  557.     }
  558.  
  559.     //
  560.     //  write the string of hex bytes out to the ini file...
  561.     //
  562.     fReturn = WritePrivateProfileString(pszSection, pszKey, psz, gszAppProfile);
  563.  
  564.     //
  565.     //  free the temporary buffer if one was allocated (lots of bytes!)
  566.     //
  567.     if (fAllocated)
  568.         GlobalFreePtr(psz);
  569.   
  570.     return (fReturn);
  571. } // AppProfileWriteBytes
  572.  
  573.  
  574. //--------------------------------------------------------------------------;
  575. //  
  576. //  BOOL AppProfileReadBytes
  577. //  
  578. //  Description:
  579. //      This function reads a previously stored structure of bytes from
  580. //      the application's ini file. This data must have been written with
  581. //      the AppProfileWriteBytes function--it is checksumed to keep bad
  582. //      data from blowing up the application.
  583. //  
  584. //      NOTE! Starting with Windows for Workgroups 3.1 there are two new
  585. //      profile functions that provide the same functionality of this
  586. //      function. Specifically, these functions are GetPrivateProfileStruct
  587. //      and WritePrivateProfileStruct. These new functions are provided
  588. //      by the Common Controls DLL. The prototypes are as follows:
  589. //
  590. //      BOOL GetPrivateProfileStruct
  591. //      (
  592. //          LPSTR       szSection,
  593. //          LPSTR       szKey,
  594. //          LPBYTE      lpStruct,
  595. //          UINT        uSizeStruct,
  596. //          LPSTR       szFile
  597. //      );
  598. //
  599. //      BOOL WritePrivateProfileStruct
  600. //      (
  601. //          LPSTR       szSection,
  602. //          LPSTR       szKey,
  603. //          LPBYTE      lpStruct,
  604. //          UINT        uSizeStruct,
  605. //          LPSTR       szFile
  606. //      );
  607. //
  608. //      If you are building an application that is for Window for Workgroups
  609. //      or newer versions of Windows, you will probably want to use the
  610. //      above functions.
  611. //  
  612. //  Arguments:
  613. //      PTSTR pszSection: Pointer to section that contains the data.
  614. //
  615. //      PTSTR pszKey: Pointer to key that contains the data.
  616. //  
  617. //      LPBYTE pbStruct: Pointer to buffer to receive the data.
  618. //  
  619. //      UINT cbStruct: Number of bytes expected.
  620. //  
  621. //  Return (BOOL):
  622. //      The return value is TRUE if the function is successful. It is FALSE
  623. //      if the function fails (bad checksum, missing key, etc).
  624. //  
  625. //  
  626. //--------------------------------------------------------------------------;
  627.  
  628. BOOL FNGLOBAL AppProfileReadBytes
  629. (
  630.     PTSTR                   pszSection,
  631.     PTSTR                   pszKey,
  632.     LPBYTE                  pbStruct,
  633.     UINT                    cbStruct
  634. )
  635. {
  636.     //
  637.     //  note that the following works for both upper and lower case, and
  638.     //  will return valid values for garbage chars
  639.     //
  640.     #define CHAR2NIBBLE(ch) (BYTE)( ((ch) >= '0' && (ch) <= '9') ?  \
  641.                                 (BYTE)((ch) - '0') :                \
  642.                                 ((BYTE)(10 + (ch) - 'A') & (BYTE)0x0F) )
  643.  
  644.     TCHAR       ach[APP_MAX_STRING_RC_CHARS];
  645.     LPTSTR      psz;
  646.     LPTSTR      pch;
  647.     UINT        cchTemp;
  648.     UINT        u;
  649.     BOOL        fAllocated;
  650.     BOOL        fReturn;
  651.     BYTE        b;
  652.     BYTE        bChecksum;
  653.     TCHAR       ch;
  654.  
  655.     //
  656.     //  add one the the number of bytes needed to accomodate the checksum
  657.     //  byte placed at the end by AppProfileWriteBytes...
  658.     //
  659.     cbStruct++;
  660.  
  661.     //
  662.     //  check if the quick buffer can be used for retrieving the input
  663.     //  text--if it cannot, then alloc space for it. note that there must
  664.     //  be space available for the null terminator (the +1 below).
  665.     //
  666.     fAllocated = FALSE;
  667.     psz        = (LPTSTR)ach;
  668.     cchTemp    = cbStruct * 2 + 1;
  669.     if (cchTemp > SIZEOF(ach))
  670.     {
  671.         psz = (LPTSTR)GlobalAllocPtr(GHND, cchTemp * sizeof(TCHAR));
  672.         if (NULL == psz)
  673.             return (FALSE);
  674.  
  675.         fAllocated = TRUE;
  676.     }
  677.  
  678.     //
  679.     //  read the hex string... if it is not the correct length, then assume
  680.     //  error and return.
  681.     //
  682.     fReturn = FALSE;
  683.     u = (UINT)GetPrivateProfileString(pszSection, pszKey, gszNull,
  684.                                       psz, cchTemp, gszAppProfile);
  685.     if ((cbStruct * 2) == u)
  686.     {
  687.         bChecksum = 0;
  688.         for (pch = psz; 0 != cbStruct; cbStruct--, pbStruct++)
  689.         {
  690.             ch = *pch++;
  691.             b  = CHAR2NIBBLE(ch) << (BYTE)4;
  692.             ch = *pch++;
  693.             b |= CHAR2NIBBLE(ch);
  694.  
  695.             //
  696.             //  if this is not the final byte (the checksum byte), then 
  697.             //  store it and accumulate checksum..
  698.             //
  699.             if (cbStruct != 1)
  700.                 bChecksum += (*pbStruct = b);
  701.         }
  702.  
  703.         //
  704.         //  check the last byte read against the checksum that we calculated
  705.         //  if they are not equal then return error...
  706.         //
  707.         fReturn = (bChecksum == b);
  708.     }
  709.  
  710.  
  711.     //
  712.     //  free the temporary buffer if one was allocated (lots of bytes!)
  713.     //
  714.     if (fAllocated)
  715.         GlobalFreePtr(psz);
  716.   
  717.     return (fReturn);
  718. } // AppProfileReadBytes
  719.  
  720.  
  721. //==========================================================================;
  722. //
  723. //  Startup and shutdown code...
  724. //
  725. //
  726. //==========================================================================;
  727.  
  728. //--------------------------------------------------------------------------;
  729. //
  730. //  BOOL AcmAppChooseFont
  731. //
  732. //  Description:
  733. //      This function lets the user choose a new font for the script window.
  734. //      After a new font is chosen, the font structure is stored to the
  735. //      .ini file so it can be restored on the next run of this application.
  736. //
  737. //  Arguments:
  738. //      HWND hwnd: Handle to main window.
  739. //
  740. //  Return (BOOL):
  741. //      The return value is TRUE if a new font was chosen. It is FALSE if
  742. //      the user canceled the operation.
  743. //
  744. //
  745. //--------------------------------------------------------------------------;
  746.  
  747. BOOL FNGLOBAL AcmAppChooseFont
  748. (
  749.     HWND                    hwnd
  750. )
  751. {
  752.     LOGFONT             lf;
  753.     HWND                hedit;
  754.     HFONT               hfont;
  755.     HFONT               hfontNew;
  756.  
  757.     hedit = GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY);
  758.  
  759.     //
  760.     //  get the current font and pass it to the choose font dialog
  761.     //
  762.     hfont = GetWindowFont(hedit);
  763.  
  764.     hfontNew = AppChooseFont(hwnd, hfont, &lf);
  765.     if (NULL == hfontNew)
  766.         return (FALSE);
  767.  
  768.     //
  769.     //  select the new font into the window and delete the old one
  770.     //
  771.     SetWindowFont(hedit, hfontNew, TRUE);
  772.     DeleteFont(hfont);
  773.  
  774.     ghfontApp = hfontNew;
  775.  
  776.  
  777.     //
  778.     //  save the complete description of the chosen font so there can be
  779.     //  no strangness in the font mapping next run. this is overkill, but
  780.     //  it works...
  781.     //
  782.     AppProfileWriteBytes(gszSecConfig, gszKeyFont, (LPBYTE)&lf, sizeof(lf));
  783.  
  784.     return (TRUE);
  785. } // AcmAppChooseFont()
  786.  
  787.  
  788. //--------------------------------------------------------------------------;
  789. //
  790. //  BOOL AcmAppSettingsRestore
  791. //
  792. //  Description:
  793. //      This function restores state information for the application. This
  794. //      function is called just after the main window is created (it has
  795. //      not been ShowWindow()'d). This function will generate the call
  796. //      to ShowWindow before returning.
  797. //
  798. //  Arguments:
  799. //      HWND hwnd: Handle to main window that has just been created but
  800. //      not shown.
  801. //
  802. //      int nCmdShow: The state that the application window should show as.
  803. //
  804. //  Return (BOOL):
  805. //      The return value is always TRUE.
  806. //
  807. //
  808. //--------------------------------------------------------------------------;
  809.  
  810. BOOL FNLOCAL AcmAppSettingsRestore
  811. (
  812.     HWND                    hwnd,
  813.     int                     nCmdShow
  814. )
  815. {
  816.     WINDOWPLACEMENT     wp;
  817.     LOGFONT             lf;
  818.     RECT                rc;
  819.     RECT                rcWindow;
  820.     POINT               pt;
  821.     int                 n;
  822.     BOOL                f;
  823.  
  824.  
  825.     //
  826.     //  restore the previous Options state...
  827.     //
  828.     gfuAppOptions = GetPrivateProfileInt(gszSecConfig, gszKeyOptions,
  829.                                          gfuAppOptions, gszAppProfile);
  830.  
  831.  
  832.  
  833.     //
  834.     //  restore the user's preferred font.
  835.     //
  836.     ghfontApp = GetStockFont(ANSI_FIXED_FONT);
  837.     f = AppProfileReadBytes(gszSecConfig, gszKeyFont, (LPBYTE)&lf, sizeof(lf));
  838.     if (f)
  839.     {
  840.         HFONT   hfont;
  841.  
  842.         hfont = CreateFontIndirect(&lf);
  843.         if (NULL != hfont)
  844.         {
  845.             ghfontApp = hfont;
  846.         }
  847.     }
  848.  
  849.     SetWindowFont(GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY), ghfontApp, FALSE);
  850.  
  851.  
  852.     //
  853.     //
  854.     //
  855.     GetPrivateProfileString(gszSecConfig, gszKeyInitialDirOpen, gszNull,
  856.                             gszInitialDirOpen, SIZEOF(gszInitialDirOpen),
  857.                             gszAppProfile);
  858.  
  859.     GetPrivateProfileString(gszSecConfig, gszKeyInitialDirSave, gszNull,
  860.                             gszInitialDirSave, SIZEOF(gszInitialDirSave),
  861.                             gszAppProfile);
  862.  
  863.     GetPrivateProfileString(gszSecConfig, gszKeyLastSaveFile, gszNull,
  864.                             gszLastSaveFile, SIZEOF(gszLastSaveFile),
  865.                             gszAppProfile);
  866.  
  867.  
  868.     //
  869.     //  grab the stored window position and size from the .ini file...
  870.     //  there must be four arguments stored or the entry is considered
  871.     //  invalid.
  872.     //
  873.     f = AppProfileReadBytes(gszSecConfig, gszKeyWindow,
  874.                             (LPBYTE)&rcWindow, sizeof(rcWindow));
  875.     if (f)
  876.     {
  877.         //
  878.         //  to make sure the user can always get at the window, check to
  879.         //  see if the midpoint of the caption is visible--if it is not,
  880.         //  then default to the default position used when creating the
  881.         //  window.
  882.         //
  883.         n = (rcWindow.right - rcWindow.left) / 2;
  884.         pt.x = (n + rcWindow.left);
  885.  
  886.         n = GetSystemMetrics(SM_CYCAPTION) / 2 + GetSystemMetrics(SM_CXFRAME);
  887.         pt.y = (n + rcWindow.top);
  888.  
  889.         GetWindowRect(GetDesktopWindow(), &rc);
  890.         if (PtInRect(&rc, pt))
  891.         {
  892.             //
  893.             //  fill out the window placement structure--default the
  894.             //  maximized and minimized states to default placement by
  895.             //  getting its current placement.
  896.             //
  897.             wp.length = sizeof(wp);
  898.             GetWindowPlacement(hwnd, &wp);
  899.  
  900.             wp.showCmd          = nCmdShow;
  901. #if 0
  902.             wp.rcNormalPosition = rcWindow;
  903. #else
  904.             n = rcWindow.right - rcWindow.left;
  905.             wp.rcNormalPosition.right  = wp.rcNormalPosition.left + n;
  906.  
  907.             n = rcWindow.bottom - rcWindow.top;
  908.             wp.rcNormalPosition.bottom = wp.rcNormalPosition.top + n;
  909. #endif
  910.  
  911.             SetWindowPlacement(hwnd, &wp);
  912.             return (TRUE);
  913.         }
  914.     }
  915.  
  916.     //
  917.     //  show defaulted and succeed
  918.     //
  919.     ShowWindow(hwnd, nCmdShow);
  920.  
  921.     return (TRUE);
  922. } // AcmAppSettingsRestore()
  923.  
  924.  
  925. //--------------------------------------------------------------------------;
  926. //
  927. //  BOOL AcmAppSettingsSave
  928. //
  929. //  Description:
  930. //      This function saves the current state information for the application.
  931. //      It is called just before the main window is closed (destroyed); or
  932. //      as Windows is exiting (query end session).
  933. //
  934. //      Note that this function should not destroy any resources--it can
  935. //      be called at any time to save a snapshot of the application state.
  936. //
  937. //  Arguments:
  938. //      HWND hwnd: Handle to main window that will be destroyed shortly.
  939. //
  940. //  Return (BOOL):
  941. //      The return value is always TRUE.
  942. //
  943. //
  944. //--------------------------------------------------------------------------;
  945.  
  946. BOOL FNLOCAL AcmAppSettingsSave
  947. (
  948.     HWND                    hwnd
  949. )
  950. {
  951.     TCHAR               ach[APP_MAX_STRING_RC_CHARS];
  952.     WINDOWPLACEMENT     wp;
  953.     PRECT               prc;
  954.     BOOL                f;
  955.  
  956.     //
  957.     //  save the current option settings--note that we ALWAYS turn off the
  958.     //  debug logging option so the app doesn't try to OutputDebugString
  959.     //  unexpectedly during the next session...
  960.     //
  961.     gfuAppOptions &= ~APP_OPTIONSF_DEBUGLOG;
  962.     if (GetPrivateProfileInt(gszSecConfig, gszKeyOptions, 0, gszAppProfile) != gfuAppOptions)
  963.     {
  964.         wsprintf(ach, gszFormatOptions, gfuAppOptions);
  965.         WritePrivateProfileString(gszSecConfig, gszKeyOptions, ach, gszAppProfile);
  966.     }
  967.  
  968.  
  969.     //
  970.     //
  971.     //
  972.     //
  973.     WritePrivateProfileString(gszSecConfig, gszKeyInitialDirOpen,
  974.                               gszInitialDirOpen, gszAppProfile);
  975.  
  976.     WritePrivateProfileString(gszSecConfig, gszKeyInitialDirSave,
  977.                               gszInitialDirSave, gszAppProfile);
  978.  
  979.     WritePrivateProfileString(gszSecConfig, gszKeyLastSaveFile,
  980.                               gszLastSaveFile, gszAppProfile);
  981.  
  982.  
  983.  
  984.     //
  985.     //  save the current window placement--only store the size and location
  986.     //  of the restored window. maximized and minimized states should
  987.     //  remain defaulted on the next invocation of this application.
  988.     //
  989.     wp.length = sizeof(wp);
  990.     f = GetWindowPlacement(hwnd, &wp);
  991.     if (f)
  992.     {
  993.         prc = &wp.rcNormalPosition;
  994.  
  995.  
  996.         //
  997.         //  save the _bounding rectangle_ of the restored window state...
  998.         //
  999.         AppProfileWriteBytes(gszSecConfig, gszKeyWindow, (LPBYTE)prc, sizeof(*prc));
  1000.     }
  1001.  
  1002.  
  1003.     //
  1004.     //  succeed
  1005.     //
  1006.     return (TRUE);
  1007. } // AcmAppSettingsSave()
  1008.  
  1009.  
  1010. //--------------------------------------------------------------------------;
  1011. //
  1012. //  BOOL AcmAppShutdown
  1013. //
  1014. //  Description:
  1015. //      This function is called to gracefully shut down the application.
  1016. //      If the application should not be closed, a FALSE value is returned.
  1017. //      This function is called for WM_CLOSE and WM_QUERYENDSESSION
  1018. //      messages...
  1019. //
  1020. //  Arguments:
  1021. //      HWND hwnd: Handle to main window.
  1022. //
  1023. //      PACMAPPFILEDESC paafd: Pointer to current file description.
  1024. //
  1025. //  Return (BOOL):
  1026. //      Returns TRUE if the application can proceed with close. Returns
  1027. //      FALSE if the application should NOT be closed.
  1028. //
  1029. //
  1030. //--------------------------------------------------------------------------;
  1031.  
  1032. BOOL FNGLOBAL AcmAppShutdown
  1033. (
  1034.     HWND                    hwnd,
  1035.     PACMAPPFILEDESC         paafd
  1036. )
  1037. {
  1038.     BOOL                f;
  1039.  
  1040.  
  1041.     //
  1042.     //  check if the script has been modified without saving. if the user
  1043.     //  cancels the operation, then we will NOT close the application.
  1044.     //
  1045.     f = AcmAppFileSaveModified(hwnd, paafd);
  1046.     if (!f)
  1047.         return (FALSE);
  1048.  
  1049.  
  1050.     //
  1051.     //
  1052.     //
  1053.     if (NULL != ghadidNotify)
  1054.     {
  1055.         acmDriverRemove(ghadidNotify, 0L);
  1056.         ghadidNotify = NULL;
  1057.     }
  1058.  
  1059.  
  1060.     //
  1061.     //  save any settings that should be saved on app termination...
  1062.     //
  1063.     AcmAppSettingsSave(hwnd);
  1064.  
  1065.  
  1066.     //
  1067.     //  allow closing of application...
  1068.     //
  1069.     return (TRUE);
  1070. } // AcmAppShutdown()
  1071.  
  1072.  
  1073. //--------------------------------------------------------------------------;
  1074. //
  1075. //  BOOL AcmAppInit
  1076. //
  1077. //  Description:
  1078. //
  1079. //
  1080. //  Arguments:
  1081. //
  1082. //
  1083. //  Return (BOOL):
  1084. //
  1085. //
  1086. //--------------------------------------------------------------------------;
  1087.  
  1088. BOOL FNLOCAL AcmAppInit
  1089. (
  1090.     HWND                    hwnd,
  1091.     PACMAPPFILEDESC         paafd,
  1092.     LPTSTR                  pszCmdLine,
  1093.     int                     nCmdShow
  1094. )
  1095. {
  1096.     BOOL                f;
  1097.     DWORD               dwVersion;
  1098.  
  1099.  
  1100.     //
  1101.     //  !!! VERY IMPORTANT !!!
  1102.     //
  1103.     //  the ACM may or may not be installed. this application is using 
  1104.     //  the ACMTHUNK.C file to dynamically link to the ACM. if the
  1105.     //  acmThunkInitialize() API fails, then the ACM is *NOT* installed
  1106.     //  and none of the API's should be used.
  1107.     //
  1108.     //  if the ACM *is* installed, then the version MUST be at least
  1109.     //  V2.00 for the API's to be available (earlier versions do not
  1110.     //  supply the API we need).
  1111.     //
  1112.     acmThunkInitialize();
  1113.  
  1114.     dwVersion = acmGetVersion();
  1115.     if (0x0200 <= HIWORD(dwVersion))
  1116.     {
  1117.         MMRESULT        mmr;
  1118.  
  1119.         gfAcmAvailable = TRUE;
  1120.  
  1121.         mmr = acmDriverAdd(&ghadidNotify,
  1122.                             ghinst,
  1123.                             (LPARAM)(UINT)hwnd,
  1124.                             WM_ACMAPP_ACM_NOTIFY,
  1125.                             ACM_DRIVERADDF_NOTIFYHWND);
  1126.         if (MMSYSERR_NOERROR != mmr)
  1127.         {
  1128.             DPF(0, "!AppCreate: acmDriverAdd failed to add notify window! mmr=%u", mmr);
  1129.         }
  1130.     }
  1131.     else
  1132.     {
  1133.         if (0L == dwVersion)
  1134.         {
  1135.             AppMsgBoxId(NULL, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  1136.                         IDS_ERROR_ACM_NOT_PRESENT);
  1137.         }
  1138.         else
  1139.         {
  1140.             AppMsgBoxId(NULL, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  1141.                         IDS_ERROR_ACM_TOO_OLD,
  1142.                         HIWORD(dwVersion) >> 8,
  1143.                         HIWORD(dwVersion) & 0x00FF);
  1144.         }
  1145.  
  1146.         gfAcmAvailable = FALSE;
  1147.     }
  1148.  
  1149.  
  1150.     //
  1151.     //
  1152.     //
  1153.     AcmAppSettingsRestore(hwnd, nCmdShow);
  1154.  
  1155.     //
  1156.     //  strip the command line..
  1157.     //
  1158.     if (NULL != pszCmdLine)
  1159.     {
  1160.         while (('\0' != *pszCmdLine) && (' ' == *pszCmdLine))
  1161.             pszCmdLine++;
  1162.     }
  1163.  
  1164.     //
  1165.     //  if there is a command line, assume it is a filename for a script
  1166.     //  and try to open it. otherwise, just initialize the script window.
  1167.     //
  1168.     if ((NULL != pszCmdLine) && ('\0' != *pszCmdLine))
  1169.     {
  1170.         //
  1171.         //  attempt to open the specified file..
  1172.         //
  1173.         lstrcpy(paafd->szFilePath, pszCmdLine);
  1174.         f = AcmAppFileOpen(hwnd, paafd);
  1175.         if (f)
  1176.         {
  1177.             AppTitle(hwnd, paafd->szFileTitle);
  1178.             AcmAppDisplayFileProperties(hwnd, paafd);
  1179.         }
  1180.         else
  1181.         {
  1182.             //
  1183.             //  opening the command line file was untriumphant..
  1184.             //
  1185.             AppMsgBoxId(hwnd, MB_OK | MB_ICONEXCLAMATION | MB_TASKMODAL,
  1186.                         IDS_ERROR_OPEN_FAILED, (LPSTR)paafd->szFilePath);
  1187.  
  1188.  
  1189.             paafd->szFilePath[0]  = '\0';
  1190.             paafd->szFileTitle[0] = '\0';
  1191.             AppFileNew(hwnd, paafd, FALSE);
  1192.         }
  1193.     }
  1194.     else
  1195.     {
  1196.         AppFileNew(hwnd, paafd, FALSE);
  1197.     }
  1198.  
  1199.     return (TRUE);
  1200. } // AcmAppInit()
  1201.  
  1202.  
  1203. //--------------------------------------------------------------------------;
  1204. //
  1205. //  BOOL AcmAppExit
  1206. //
  1207. //  Description:
  1208. //
  1209. //
  1210. //  Arguments:
  1211. //
  1212. //
  1213. //  Return (BOOL):
  1214. //
  1215. //
  1216. //
  1217. //--------------------------------------------------------------------------;
  1218.  
  1219. BOOL FNGLOBAL AcmAppExit
  1220. (
  1221.     void
  1222. )
  1223. {
  1224.     acmThunkTerminate();
  1225.  
  1226.     return (TRUE);
  1227. } // AcmAppExit()
  1228.  
  1229.  
  1230. //==========================================================================;
  1231. //
  1232. //  Initialization and exit code...
  1233. //
  1234. //
  1235. //==========================================================================;
  1236.  
  1237. //--------------------------------------------------------------------------;
  1238. //
  1239. //  BOOL AppRegisterPenApp
  1240. //
  1241. //  Description:
  1242. //      This function is used to register and de-register an application
  1243. //      as being 'Pen Enhanced.' If the Windows installation is Pen enabled
  1244. //      then this function allows the RC Manager to replace all 'Edit'
  1245. //      controls with 'HEdit' controls.
  1246. //
  1247. //      This function must be called to register the application BEFORE
  1248. //      creating any edit controls.
  1249. //
  1250. //  Arguments:
  1251. //      BOOL fRegister: If this argument is TRUE, the app is registered
  1252. //      with the RC Manager as being Pen aware. If this argument is FALSE
  1253. //      the app is de-registered.
  1254. //
  1255. //  Return (BOOL):
  1256. //      The return value is TRUE if Windows for Pen Computing is installed
  1257. //      on the system. The return value is FALSE if the Windows installation
  1258. //      is not Pen enabled.
  1259. //
  1260. //
  1261. //--------------------------------------------------------------------------;
  1262.  
  1263. BOOL FNLOCAL AppRegisterPenApp
  1264. (
  1265.     BOOL                    fRegister
  1266. )
  1267. {
  1268.     #define RPA_DEFAULT     0x0001
  1269.  
  1270.     typedef void (FAR PASCAL *PENWINREGISTERPROC)(UINT, BOOL);
  1271.  
  1272.     static char                 szRegPenApp[]   = "RegisterPenApp";
  1273.     static PENWINREGISTERPROC   pfnRegPenApp    = NULL;
  1274.  
  1275.     HINSTANCE   hinstPenWin;
  1276.  
  1277.     //
  1278.     //  check if Windows for Pen Computing is installed--and if it is, 
  1279.     //  dyna-link to the RegisterPenApp() function.
  1280.     //
  1281.     //  if Pens are not supported, then return FALSE.
  1282.     //
  1283.     if (NULL == pfnRegPenApp)
  1284.     {
  1285.         hinstPenWin = (HINSTANCE)GetSystemMetrics(SM_PENWINDOWS);
  1286.         if (NULL == hinstPenWin)
  1287.             return (FALSE);
  1288.  
  1289.         pfnRegPenApp = (PENWINREGISTERPROC)GetProcAddress(hinstPenWin, szRegPenApp);
  1290.         if (NULL == pfnRegPenApp)
  1291.             return (FALSE);
  1292.     }
  1293.  
  1294.     //
  1295.     //  either enable or disable the RC Manager's Pen meathooks..
  1296.     //
  1297.     (*pfnRegPenApp)(RPA_DEFAULT, fRegister);
  1298.  
  1299.     return (TRUE);
  1300. } // AppRegisterPenApp()
  1301.  
  1302.  
  1303. //--------------------------------------------------------------------------;
  1304. //
  1305. //  LRESULT AppCreate
  1306. //
  1307. //  Description:
  1308. //      This function is called to handle the WM_CREATE message for the
  1309. //      applications window. The application should finish the creation
  1310. //      of the window (create controls, allocate resources, etc). The
  1311. //      window has not been displayed (CreateWindow[Ex] has not returned).
  1312. //
  1313. //  Arguments:
  1314. //      HWND hwnd: Handle to the window that is in the process of being
  1315. //      created.
  1316. //
  1317. //      LPCREATESTRUCT pcs: Pointer to a CREATESTRUCT that contains info
  1318. //      about the window being created.
  1319. //
  1320. //  Return (LRESULT):
  1321. //      The return value should be nonzero if the application wishes to
  1322. //      let the window finish being created. A return of zero tells
  1323. //      CreateWindow[Ex] to fail the creation of the window.
  1324. //
  1325. //
  1326. //--------------------------------------------------------------------------;
  1327.  
  1328. LRESULT FNGLOBAL AppCreate
  1329. (
  1330.     HWND                    hwnd,
  1331.     LPCREATESTRUCT          pcs
  1332. )
  1333. {
  1334.     static TCHAR        szEdit[]    = TEXT("edit");
  1335.  
  1336.     HWND                hedit;
  1337.  
  1338.     DPF(1, "AppCreate(hwnd=%Xh, cs.x=%d, cs.y=%d, cs.cx=%d, cs.cy=%d)",
  1339.             hwnd, pcs->x, pcs->y, pcs->cx, pcs->cy);
  1340.  
  1341.     //
  1342.     //  create the driver selection listbox
  1343.     //
  1344.     hedit = CreateWindow(szEdit, gszNull,
  1345.                          ES_LEFT | ES_MULTILINE | WS_TABSTOP |
  1346.                          ES_AUTOVSCROLL | ES_AUTOHSCROLL |
  1347.                          ES_NOHIDESEL | WS_BORDER | WS_VSCROLL | WS_HSCROLL |
  1348.                          WS_VISIBLE | WS_CHILD | ES_READONLY,
  1349.                          0, 0, 0, 0, hwnd, (HMENU)IDD_ACMAPP_EDIT_DISPLAY,
  1350.                          pcs->hInstance, NULL);
  1351.     if (NULL == hedit)
  1352.         return (0L);
  1353.  
  1354.  
  1355.     //
  1356.     //  return nonzero to succeed the creation of the window
  1357.     //
  1358.     return (1L);
  1359. } // AppCreate()
  1360.  
  1361.  
  1362. //--------------------------------------------------------------------------;
  1363. //
  1364. //  LRESULT AppQueryEndSession
  1365. //
  1366. //  Description:
  1367. //      This function handles the WM_QUERYENDSESSION. This message is sent
  1368. //      by USER when ExitWindows has been called to end the Windows session.
  1369. //      This function can stop Windows from exiting if it is not convenient
  1370. //      for Windows to end.
  1371. //
  1372. //      Giving the user the option to save modified data before continueing
  1373. //      with the shutdown of Windows is a good idea.
  1374. //
  1375. //      Telling Windows to continue with the exit procedure does not
  1376. //      necessarily mean Windows will exit. All applications are queried
  1377. //      for shutdown approval. When the actual decision is made on whether
  1378. //      Windows will exit, WM_ENDSESSION will be sent with the result.
  1379. //
  1380. //  Arguments:
  1381. //      HWND hwnd: Handle to window that received the message.
  1382. //
  1383. //  Return (LRESULT):
  1384. //      Returns zero to STOP Windows from exiting. Returns non-zero to
  1385. //      allows windows to shut down.
  1386. //
  1387. //
  1388. //--------------------------------------------------------------------------;
  1389.  
  1390. LRESULT FNGLOBAL AppQueryEndSession
  1391. (
  1392.     HWND                    hwnd
  1393. )
  1394. {
  1395.     BOOL                f;
  1396.  
  1397.     DPF(1, "AppQueryEndSession(hwnd=%Xh)", hwnd);
  1398.  
  1399.     //
  1400.     //  attempt to shut down--if this fails (user canceled it, etc) then
  1401.     //  do NOT allow the Windows to exit.
  1402.     //
  1403.     f = AcmAppShutdown(hwnd, &gaafd);
  1404.     if (!f)
  1405.         return (0L);
  1406.  
  1407.  
  1408.     //
  1409.     //  tell Windows to proceed with the shutdown process!
  1410.     //
  1411.     return (1L);
  1412. } // AppQueryEndSession()
  1413.  
  1414.  
  1415. //--------------------------------------------------------------------------;
  1416. //
  1417. //  LRESULT AppEndSession
  1418. //
  1419. //  Description:
  1420. //      This function is called to handle the WM_ENDSESSION message. This
  1421. //      message is generated after the application answers the
  1422. //      WM_QUERYENDSESSION message. The purpose of the WM_ENDSESSION
  1423. //      message is to tell the application if Windows will be exiting
  1424. //      (TRUE  == fEndSession) or the end session was canceled by an
  1425. //      application (FALSE == fEndSession).
  1426. //
  1427. //  Arguments:
  1428. //      HWND hwnd: Handle to window that received the message.
  1429. //
  1430. //      BOOL fEndSession: TRUE if Windows is exiting. FALSE if the end
  1431. //      session was canceled.
  1432. //
  1433. //  Return (LRESULT):
  1434. //      Returns zero if the message is processed. Note that an application
  1435. //      cannot halt the termination of Windows from this message--the
  1436. //      WM_QUERYENDSESSION is the only message that allows that behaviour.
  1437. //      If fEndSession is TRUE, Windows *WILL* exit--whether you like it
  1438. //      or not.
  1439. //
  1440. //
  1441. //--------------------------------------------------------------------------;
  1442.  
  1443. LRESULT FNGLOBAL AppEndSession
  1444. (
  1445.     HWND                    hwnd,
  1446.     BOOL                    fEndSession
  1447. )
  1448. {
  1449.     DPF(1, "AppEndSession(hwnd=%Xh, fEndSession=%d)", hwnd, fEndSession);
  1450.  
  1451.     //
  1452.     //  we processed the message, return zero..
  1453.     //
  1454.     return (0L);
  1455. } // AppEndSession()
  1456.  
  1457.  
  1458. //--------------------------------------------------------------------------;
  1459. //
  1460. //  LRESULT AppClose
  1461. //
  1462. //  Description:
  1463. //      This function handles the WM_CLOSE message for the application.
  1464. //      If the application should close, DestroyWindow() must be called
  1465. //      by this function. Otherwise the application will not close.
  1466. //
  1467. //  Arguments:
  1468. //      HWND hwnd: Handle to window that generated the WM_CLOSE message.
  1469. //
  1470. //  Return (LRESULT):
  1471. //      There return value is zero. The DestroyWindow function will have
  1472. //      been called if the application should actually close.
  1473. //
  1474. //--------------------------------------------------------------------------;
  1475.  
  1476. LRESULT FNGLOBAL AppClose
  1477. (
  1478.     HWND                    hwnd
  1479. )
  1480. {
  1481.     HWND                hedit;
  1482.     HFONT               hfont;
  1483.     BOOL                f;
  1484.  
  1485.     //
  1486.     //  if the Shift key is held down during the close message, then just
  1487.     //  save the current state but don't destroy the window... this is
  1488.     //  useful if the user does not want to exit the app and rerun it
  1489.     //  to make sure the state is saved--just before the user does something
  1490.     //  that may crash Windows or something..
  1491.     //
  1492.     if (GetKeyState(VK_SHIFT) < 0)
  1493.     {
  1494.         //
  1495.         //  save any settings that should be saved on app termination...
  1496.         //
  1497.         AcmAppSettingsSave(hwnd);
  1498.         return (0L);
  1499.     }
  1500.  
  1501.     //
  1502.     //  attempt to shut down--if this fails (user canceled it, etc) then
  1503.     //  do NOT allow the window to be destroyed.
  1504.     //
  1505.     f = AcmAppShutdown(hwnd, &gaafd);
  1506.     if (!f)
  1507.         return (0L);
  1508.  
  1509.  
  1510.  
  1511.     //
  1512.     //  destroy the font we are using... before deleting the font, select
  1513.     //  the system font back into the window so the font won't be 'in use'
  1514.     //  anymore.
  1515.     //
  1516.     hedit = GetDlgItem(hwnd, IDD_ACMAPP_EDIT_DISPLAY);
  1517.  
  1518.     hfont = GetWindowFont(hedit);
  1519.     SetWindowFont(hedit, NULL, FALSE);
  1520.     DeleteFont(hfont);
  1521.  
  1522.     ghfontApp = NULL;
  1523.  
  1524.     //
  1525.     //  make the window close and terminate the application
  1526.     //
  1527.     DestroyWindow(hwnd);
  1528.  
  1529.     return (0L);
  1530. } // AppClose()
  1531.  
  1532.  
  1533. //--------------------------------------------------------------------------;
  1534. //
  1535. //  BOOL AppInit
  1536. //
  1537. //  Description:
  1538. //      This function is called to initialize a new instance of the
  1539. //      application. We want to parse our command line, create our window,
  1540. //      allocate resources, etc.
  1541. //
  1542. //      The arguments passed to this function are exactly the same as
  1543. //      those passed to WinMain.
  1544. //
  1545. //  Arguments:
  1546. //      HINSTANCE hinst: Identifies the current instance of the
  1547. //      application.
  1548. //
  1549. //      HINSTANCE hinstPrev: Identifies the previous instance of the
  1550. //      application (NULL if first instance). For Win 32, this argument
  1551. //      is _always_ NULL.
  1552. //
  1553. //      LPTSTR pszCmdLine: Points to null-terminated unparsed command line.
  1554. //      If the application is compiled for Unicode, then this argument is
  1555. //      ignored.
  1556. //
  1557. //      int nCmdShow: How the main window for the application is to be
  1558. //      shown by default.
  1559. //
  1560. //  Return (HWND):
  1561. //      Returns the newly created handle to the applications main window.
  1562. //      This handle is NULL if something went wrong and tells the application
  1563. //      to exit immediately.
  1564. //
  1565. //
  1566. //--------------------------------------------------------------------------;
  1567.  
  1568. HWND FNGLOBAL AppInit
  1569. (
  1570.     HINSTANCE               hinst,
  1571.     HINSTANCE               hinstPrev,
  1572.     LPTSTR                  pszCmdLine,
  1573.     int                     nCmdShow
  1574. )
  1575. {
  1576.     HWND                hwnd;
  1577.     WNDCLASS            wc;
  1578.  
  1579.     DPF(1, "AppInit(hinst=%Xh, hinstPrev=%Xh, pszCmdLine='%s', nCmdShow=%d)",
  1580.             hinst, hinstPrev, pszCmdLine, nCmdShow);
  1581.  
  1582.     LoadString(hinst, IDS_APP_NAME, gszAppName, SIZEOF(gszAppName));
  1583.     LoadString(hinst, IDS_FILE_UNTITLED, gszFileUntitled, SIZEOF(gszFileUntitled));
  1584.  
  1585.  
  1586.     //
  1587.     //  determine whether a new window class needs to be registered for
  1588.     //  this application. for Win 16, this only needs to be done for the
  1589.     //  first instance of the application created. for Win 32, this must
  1590.     //  be done for EVERY instance of the application.
  1591.     //
  1592.     if (NULL == hinstPrev)
  1593.     {
  1594.         wc.style         = CS_HREDRAW | CS_VREDRAW;
  1595.         wc.lpfnWndProc   = (WNDPROC)AppWndProc;
  1596.         wc.cbClsExtra    = 0;
  1597.         wc.cbWndExtra    = 0;
  1598.         wc.hInstance     = hinst;
  1599.         wc.hIcon         = LoadIcon(hinst, ICON_APP);
  1600.         wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  1601.         wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
  1602.         wc.lpszMenuName  = MENU_APP;
  1603.         wc.lpszClassName = gszAppName;
  1604.  
  1605.         if (!RegisterClass(&wc))
  1606.             return (NULL);
  1607.     }
  1608.  
  1609.  
  1610.     //
  1611.     //  if Windows for Pen Computing is installed, then allow the RC
  1612.     //  Manager to replace all edit controls created from this point on
  1613.     //  with hedit controls
  1614.     //
  1615.     AppRegisterPenApp(TRUE);
  1616.  
  1617.  
  1618.     //
  1619.     //  create the application's main window
  1620.     //
  1621.     //  style bits available:
  1622.     //      WS_EX_ACCEPTFILES   :  will receive WM_DROPFILES messages
  1623.     //      WS_EX_DLGMODALFRAME :  creates window with double border
  1624.     //      WS_EX_NOPARENTNOTIFY:  won't receive WM_PARENTNOTIFY messages
  1625.     //      WS_EX_TOPMOST       :  puts window in topmost space
  1626.     //      WS_EX_TRANSPARENT   :  a very bizarre style indeed (Win 16 only)
  1627.     //
  1628.     hwnd = CreateWindowEx(WS_EX_ACCEPTFILES | WS_EX_NOPARENTNOTIFY,
  1629.                           gszAppName,
  1630.                           gszAppName,
  1631.                           WS_OVERLAPPEDWINDOW,
  1632.                           APP_WINDOW_XOFFSET,
  1633.                           APP_WINDOW_YOFFSET,
  1634.                           APP_WINDOW_WIDTH,
  1635.                           APP_WINDOW_HEIGHT,
  1636.                           NULL,
  1637.                           NULL,
  1638.                           hinst,
  1639.                           NULL);
  1640.  
  1641.     if (NULL == hwnd)
  1642.         return (NULL);
  1643.  
  1644.  
  1645. #ifdef UNICODE
  1646.     //
  1647.     //  GetCommandLine() returns a pointer to our command line. but this
  1648.     //  command line includes the complete command line used to launch
  1649.     //  the application--which is different than the pszCmdLine argument
  1650.     //  passed through WinMain()...
  1651.     //
  1652.     //  so, skip over the command name to get to the argument string
  1653.     //
  1654.     pszCmdLine = GetCommandLine();
  1655.     if (NULL != pszCmdLine)
  1656.     {
  1657.         while (('\0' != *pszCmdLine) && (' ' != *pszCmdLine++))
  1658.             ;
  1659.     }
  1660. #endif
  1661.  
  1662.  
  1663.     //
  1664.     //
  1665.     //
  1666.     //
  1667.     AcmAppInit(hwnd, &gaafd, pszCmdLine, nCmdShow);
  1668.  
  1669.  
  1670.     //
  1671.     //  finally, get the window displayed and return success
  1672.     //
  1673.     //  the ShowWindow call is made during AcmAppInit
  1674.     //
  1675. //  ShowWindow(hwnd, nCmdShow);
  1676. //  UpdateWindow(hwnd);
  1677.  
  1678.     return (hwnd);
  1679. } // AppInit()
  1680.  
  1681.  
  1682. //--------------------------------------------------------------------------;
  1683. //
  1684. //  int AppExit
  1685. //
  1686. //  Description:
  1687. //      This function is called just before the application exits from
  1688. //      WinMain. Its purpose is to clean up any resources that were allocated
  1689. //      for running the application: brushes, heaps, etc..
  1690. //
  1691. //  Arguments:
  1692. //      HINSTANCE hinst: Identifies the current instance of the
  1693. //      application that is exiting.
  1694. //
  1695. //      int nResult: The result of the WM_QUIT message (in wParam of the
  1696. //      MSG structure. This argument will usually be 0 (even if the message
  1697. //      loop was never entered).
  1698. //
  1699. //  Return (int):
  1700. //      The return value is usually nResult--be we give this function the
  1701. //      opportunity to modify its value.
  1702. //
  1703. //
  1704. //--------------------------------------------------------------------------;
  1705.  
  1706. int FNGLOBAL AppExit
  1707. (
  1708.     HINSTANCE               hinst,
  1709.     int                     nResult
  1710. )
  1711. {
  1712.     DPF(1, "AppExit(hinst=%Xh, nResult=%d)", hinst, nResult);
  1713.  
  1714.     AcmAppExit();
  1715.  
  1716.     //
  1717.     //  if Windows for Pen Computing is installed, then de-register the
  1718.     //  application so the RC Manager knows we will no longer need its
  1719.     //  services...
  1720.     //
  1721.     AppRegisterPenApp(FALSE);
  1722.  
  1723.     return (nResult);
  1724. } // AppExit()
  1725.  
  1726.  
  1727. //==========================================================================;
  1728. //
  1729. //  Misc rarely used application dialogs and stuff...
  1730. //
  1731. //
  1732. //==========================================================================;
  1733.  
  1734. //--------------------------------------------------------------------------;
  1735. //
  1736. //  BOOL AboutDlgProc
  1737. //
  1738. //  Description:
  1739. //      This dialog procedure is used for the ubiquitous about box.
  1740. //
  1741. //  Arguments:
  1742. //      HWND hwnd: Handle to window.
  1743. //
  1744. //      UINT uMsg: Message being sent to the window.
  1745. //
  1746. //      WPARAM wParam: Specific argument to message.
  1747. //
  1748. //      LPARAM lParam: Specific argument to message.
  1749. //
  1750. //  Return (BOOL):
  1751. //      The return value is specific to the message that was received. For
  1752. //      the most part, it is FALSE if this dialog procedure does not handle
  1753. //      a message.
  1754. //
  1755. //
  1756. //--------------------------------------------------------------------------;
  1757.  
  1758. BOOL FNEXPORT AboutDlgProc
  1759. (
  1760.     HWND                    hwnd,
  1761.     UINT                    uMsg,
  1762.     WPARAM                  wParam,
  1763.     LPARAM                  lParam
  1764. )
  1765. {
  1766.     HWND                hwndT;
  1767.     PTSTR               pach;
  1768.     UINT                u;
  1769.  
  1770.     switch (uMsg)
  1771.     {
  1772.         case WM_INITDIALOG:
  1773.             //
  1774.             //  display some OS version information
  1775.             //
  1776.             //
  1777.             pach = (PTSTR)LocalAlloc(LPTR, APP_MAX_STRING_RC_BYTES);
  1778.             if (NULL == pach)
  1779.                 return (TRUE);
  1780.  
  1781.             AppGetWindowsVersion(pach, NULL);
  1782.             hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_OS);
  1783.             SetWindowText(hwndT, pach);
  1784.  
  1785.             AppGetWindowsVersion(NULL, pach);
  1786.             hwndT = GetDlgItem(hwnd, IDD_ABOUT_VERSION_PLATFORM);
  1787.             SetWindowText(hwndT, pach);
  1788.  
  1789.             LocalFree((HLOCAL)pach);
  1790.  
  1791.             return (TRUE);
  1792.  
  1793.         case WM_COMMAND:
  1794.             u = GET_WM_COMMAND_ID(wParam, lParam);
  1795.             if ((IDOK == u) || (IDCANCEL == u))
  1796.             {
  1797.                 EndDialog(hwnd, (IDOK == u));
  1798.             }
  1799.             break;
  1800.     }
  1801.  
  1802.     return (FALSE);
  1803. } // AboutDlgProc()
  1804.